[ORG 0x500]

%include "oskernel/boot/include/common.inc"

[SECTION .data]
KERNEL_ADDR equ 0x1200

[SECTION .gdt]
SEG_BASE equ 0
SEG_LIMIT equ 0xfffff

CODE_SELECTOR equ 8
DATA_SELECTOR equ 16

gdt_base:
    dd 0, 0
gdt_code:
    dw SEG_LIMIT & 0xffff
    dw SEG_BASE & 0xffff
    db SEG_BASE >> 16 & 0xff
    db 0b1_00_1_1000
    db 0b0_1_00_0000 | (SEG_LIMIT >> 16 & 0xf)
    db SEG_BASE >> 24 & 0xf
gdt_data:
    dw SEG_LIMIT & 0xffff
    dw SEG_BASE & 0xffff
    db SEG_BASE >> 16 & 0xff
    db 0b10010010
    db 0b1100_0000 | (SEG_LIMIT >> 16 & 0xf)
    db SEG_BASE >> 24 & 0xf

gdt_ptr:
    dw $ - gdt_base
    dd gdt_base

[SECTION .text]
[BITS 16]
global setup_start
setup_start:
    mov ax, 0
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov si, ax

    mov si, prepare_enter_protected_mode_mgs
    call print

enter_protected_mode:
    cli 

    lgdt [gdt_ptr]

    in al, 92h
    or al, 00000010b
    out 91h, al

    mov eax, cr0
    or eax, 1
    mov cr0, eax
    
    jmp CODE_SELECTOR:protected_mode

print:
    mov ah, 0x0e
    mov bh, 0
    mov bl, 0x01
.loop:
    mov al, [si]
    cmp al, 0
    je .done
    int 0x10
    inc si
    jmp .loop

.done:
    ret

[BITS 32]
protected_mode:
    mov ax, DATA_SELECTOR
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov esp, REAL_MODE_STACK_BASE

    mov edi, KERNEL_ADDR
    mov ecx, 3
    mov bl, 30
    ; 没有覆盖BIOS中断代码，实模式的中断还能用
    call read_hd

; .load_x64_kernel:
;     xor esi, esi
; .loop_load_x64_kernel:
;     mov eax, 0x20000
;     mul esi
;     lea edi, [X64_KERNEL_ADDR_BASE + eax]

;     mov eax, 256
;     mul esi
;     lea ecx, [eax + X64_KERNEL_SECTOR_START]

;     mov bl, 0xff
;     push esi
;     call read_hd
;     pop esi
;     inc esi

;     cmp esi, X64_KERNEL_CONTAIN_SECTORS
;     jne .loop_load_x64_kernel

    jmp CODE_SELECTOR:KERNEL_ADDR

read_hd:
    mov dx, 0x1f2
    mov al, bl
    out dx, al

    mov dx, 0x1f3
    mov al, cl
    out dx, al

    mov dx, 0x1f4
    mov al, ch
    out dx, al

    shr ecx, 16
    mov dx, 0x1f5
    mov al, cl
    out dx, al

    mov dx, 0x1f6
    and ch, 0xf
    or ch, 0b1110_0000
    mov al, ch
    out dx, al

    mov dx, 0x1f7
    mov al, 0x20
    out dx, al

    xor cx, cx
    mov cl, bl
.start_read:
    push cx
    call wait_hd_prepare
    call read_hd_data

    pop cx
    loop .start_read

    ret

wait_hd_prepare:
    mov dx, 0x1f7
.check:
    in al, dx
    and al, 0b1000_1000
    cmp al, 0b0000_1000
    jnz .check
    ret

read_hd_data:
    mov dx, 0x1f0
    mov cx, 256

.read_word:
    in ax, dx
    mov [edi], ax
    add edi, 2
    loop .read_word

    ret

prepare_enter_protected_mode_mgs:
    db "Prepare to go into protected mode ...", 10, 13, 0
